package com.pxxy.springmvc.controller;

import com.pxxy.springmvc.entity.Book;
import com.pxxy.springmvc.entity.Result;
import com.pxxy.springmvc.service.BookService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

/******************
 * @Author yejf
 * @Description TODO
 */
@Controller
@RequestMapping("/book")
public class BookController {

    private static final Logger log = LoggerFactory.getLogger(BookController.class);

    private static final String COVER_UPLOAD_DIR = "static/images/book_cover_img";

    @Autowired
    private BookService bookService;

    /*@ExceptionHandler(value = RuntimeException.class)
    public void handlerException(Exception ex) {
        //此Controller中，任一个打上了 @RequestMapping的方法出现 RuntimeException 异常时，就会回调此方法
        System.out.println("-- BookContorller的handlerException方法被调用了...");
        System.out.println("ex = " + ex);
    }*/

    @RequestMapping("/list.do")
    public String list(Model model) {
        //1. 直接调用业务层来获取业务数据
        final List<Book> books = this.bookService.findAll();
        //2. 把数据绑定到模型当中
        model.addAttribute("BOOK_LIST", books);
        //3. 返回逻辑视图名
        return "book/list";  //最终目的地：/WEB/INF/jsp/book/list.jsp
    }

    @RequestMapping(value = "/deleteSelect.do", produces = "text/html;charset=utf-8")
    @ResponseBody  //以内容来响应客户端
    //public String deleteSelected(@RequestParam(value = "flags",required = false) List<Integer> idList) {
    public String deleteSelected(@RequestBody List<Integer> idList) {
        log.debug("Spring MVC帮助封装了请求参数 idList："+idList);
        //调用业务方法
        if(this.bookService.deleteSelected(idList) > 0) {
            return "删除成功";  //这个返回值 会写回到 客户端
        } else {
            return "删除失败";
        }
    }

    @RequestMapping(value = "/add.do", method = RequestMethod.POST, produces = "application/json")
    @ResponseBody
    public Object add(HttpServletRequest request, @Valid Book book,BindingResult bindingResult,
                      @RequestParam("coverUrlFile") MultipartFile coverUrl) {
        //判断 bindingResult是否存在 bean 验证后的错误信息
        if(bindingResult.hasErrors()) {
            //说明验证没有通过，则把错误绑定前端的页面
            final List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            for(FieldError fe : fieldErrors) {
                System.out.println(fe.getField()+" => "+fe.getDefaultMessage());
            }
            //return "error";
            return new Result("failure",fieldErrors);
        } else {
            //spring mvc 会把前端表单中的表单域全部封装到 book 变量之中，而 coverUrlFile 则会封装到 MultipartFile对象中
            //获取图片上传后的真正目录
            String realPath = request.getServletContext().getRealPath(COVER_UPLOAD_DIR);
            //1. 完成文件的上传
            final String originalFilename = coverUrl.getOriginalFilename();
            //生成一个新的文件名
            String fileName = UUID.randomUUID().toString();
            //获取原来文件的扩展名
            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            fileName += suffix;
            //IO流操作
            try {
                coverUrl.transferTo(new File(realPath + File.separatorChar + fileName));
                System.out.println("上传成功，文件名为:" + fileName);
            } catch (IOException e) {
                log.error("上传图片失败", e);
                //重新抛出
                throw new RuntimeException(e);
            }
            //即使图片上传失败，图书信息 也要写到数据库
            //重新图书封面信息
            book.setCoverUrl(fileName);
            //调用业务层方法，写到数据库中
            this.bookService.save(book);
            //跳转到JSP
            //return book;
            return new Result("success", book);
        }
    }

    @RequestMapping(value = "/delete.do",produces = "text/plain;charset=utf-8")
    @ResponseBody
    public String delete(Integer id) {
        //调用业务方法
        if(this.bookService.delete(id) > 0) {
            return "删除图书成功，id:"+id;
        } else {
            return "删除失败";
        }
    }

    @RequestMapping(value = "/toUpdate.do", produces = "application/json")
    @ResponseBody
    public Book toUpdate(Integer id) {
        //
        return this.bookService.findById(id);
    }

    @RequestMapping(value = "/search.do")
    public String search(@RequestParam(value = "search", required = false)
                                     String search,
                                        Model model) {
        //
       /* if(Math.random() < 0.9) {
            throw new RuntimeException("出异常了");
        }*/
        //调用业务层方法
        final List<Book> bookList = this.bookService.findByKeyword(search);
        //
        model.addAttribute("BOOK_LIST",bookList);
        //把查询关键字带回到前端页面
        model.addAttribute("search",search);
        //返回逻辑视图名
        return "book/list";
    }
}
